﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.Xml;
using System.ComponentModel;

using ShootSearch.Util;
using ShootSearch.Util.Serializers;
using ShootSearch.Core.ObjectItems;

namespace ShootSearch.Core
{
    [Serializable]
    [TypeConverter(typeof(ExpandableConverter<TaskConfig>))]
    public class AssemblyWithConfig : IXmlSerializable
    {

        protected SpiderManConfig config;
        protected AssemblyConfig configType;


        //public string Name { get; set; }
        public AssemblyConfig Type { get; set; }
        public AssemblyConfig ConfigType
        {
            get { return configType; }
            set
            {
                this.configType = value;
                if (value != null)
                {
                    config = value.GetObject() as SpiderManConfig;
                }

            }
        }

        public SpiderManConfig Config
        {
            get { return config; }
            set
            {
                config = value;
                if (value != null)
                {
                    configType = new AssemblyConfig(value.GetType());
                }
            }
        }

        public AssemblyWithConfig()
        {
            Type = new AssemblyConfig();
            ConfigType = new AssemblyConfig();
        }

        public AssemblyWithConfig(IConfigable obj)
        {
            if (obj != null)
            {
                Type = new AssemblyConfig(obj.GetType());
                if (obj.Config != null)
                {
                    Config = obj.Config;
                }
            }
        }

        public AssemblyWithConfig(Type type)
        {
            if (type != null)
            {
                Type = new AssemblyConfig(type);
                IConfigable obj = type.Assembly.CreateInstance(type.FullName) as IConfigable;
                if (obj != null)
                {
                    Config = obj.Config;
                }
            }
        }


        public AssemblyWithConfig(Type type, SpiderManConfig config)
        {
            if (type != null)
            {
                Type = new AssemblyConfig(type);
                Config = config;
            }
        }


        #region IXmlSerializable Members

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return new System.Xml.Schema.XmlSchema();
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {

            Type = new AssemblyConfig();
            reader.ReadToFollowing("Type");
            reader.MoveToAttribute("TypeName");
            Type.TypeName = reader.Value;
            reader.MoveToAttribute("Assembly");
            Type.Assembly = reader.Value;

            ConfigType = new AssemblyConfig();
            reader.ReadToFollowing("ConfigType");
            reader.MoveToAttribute("TypeName");
            ConfigType.TypeName = reader.Value;
            reader.MoveToAttribute("Assembly");
            ConfigType.Assembly = reader.Value;

            object obj = ConfigType.GetObject();
            if (obj != null)
            {
                Type type = obj.GetType();
                if (type != null)
                {
                    reader.ReadToFollowing(type.Name);
                    Config = XmlFormatter.FromXml(reader.ReadOuterXml(), type) as SpiderManConfig;

                }
            }
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {


            writer.WriteStartElement("Type");
            if (Type != null)
            {
                writer.WriteAttributeString("TypeName", Type.TypeName);
                writer.WriteAttributeString("Assembly", Type.Assembly);
            } 
            writer.WriteEndElement();

            writer.WriteStartElement("ConfigType");
            if (ConfigType != null)
            {
                writer.WriteAttributeString("TypeName", ConfigType.TypeName);
                writer.WriteAttributeString("Assembly", ConfigType.Assembly);
            }
            writer.WriteEndElement();

            XmlFormatter.ToXml(writer, Config);
        }

        #endregion

        public object GetObject()
        {
            if (Type != null) return Type.GetObject();
            else return null;
        }


        public IConfigable GetObjectWithConfig()
        {
            if (Type != null) 
            {
                IConfigable obj = Type.GetObject() as IConfigable;
                if (obj != null)
                {
                    obj.Config = this.Config;
                    return obj;
                }
            }
            return null;
        }
    }
}
